package org.planx.xmlstore.routing.operation;

import java.io.*;
import java.math.*;
import java.net.*;
import java.util.*;
import junit.framework.*;
import org.planx.xmlstore.routing.*;
import org.planx.xmlstore.routing.messaging.*;

/**
 * Tests that messages can successfully be converted to byte arrays and recreated
 * from byte arrays.
 **/
public class MessageTest extends TestCase {

    public MessageTest(String s) {
        super(s);
    }

    public static Test suite() {
        return new TestSuite(MessageTest.class);
    }

    public static void main(String args[]) {
        junit.textui.TestRunner.run(MessageTest.class);
    }

    protected void printByteArray(byte[] data) {
        for (int i=0;i<data.length;i++) {
            if (i>0) System.out.print(",");
            String s = Integer.toHexString((int) data[i]);
            s = (s.length() > 1) ? s.substring(s.length()-2) : "0"+s;
            System.out.print(s);
        }
        System.out.println();
    }

    public void testIdentifierStreamable1() throws IOException {
        Identifier id = new Identifier(BigInteger.ONE);
        identifierTest(id);
    }

    public void testIdentifierStreamable2() throws IOException {
        Identifier id = new Identifier(BigInteger.ONE.shiftLeft(Identifier.IDSIZE-1));
        identifierTest(id);
    }

    public void testIdentifierStreamable3() throws IOException {
        Identifier id = Identifier.randomIdentifier();
        identifierTest(id);
    }

    private void identifierTest(Identifier id) throws IOException {
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        DataOutputStream dout = new DataOutputStream(bout);
        id.toStream(dout);
        byte[] data = bout.toByteArray();

        DataInputStream din = new DataInputStream(new ByteArrayInputStream(data));
        Identifier inid = new Identifier(din);
        assertEquals(id, inid);
    }

    public void testNodeLookupMessage() throws IOException {
        Node node = new Node(InetAddress.getByName("172.16.1.223"),
                                           65530, Identifier.randomIdentifier());
        Identifier id = Identifier.randomIdentifier();
        Message mess = new NodeLookupMessage(node, id);
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        DataOutputStream dout = new DataOutputStream(bout);
        mess.toStream(dout);
        byte[] data = bout.toByteArray();

        DataInputStream din = new DataInputStream(new ByteArrayInputStream(data));
        NodeLookupMessage incm = new NodeLookupMessage(din);

        assertEquals(node.getInetAddress(), incm.getOrigin().getInetAddress());
        assertEquals(node.getPort(), incm.getOrigin().getPort());
        assertEquals(node.getId(), incm.getOrigin().getId());
        assertEquals(node, incm.getOrigin());
        assertEquals(id, incm.getLookupId());
    }

    public void testLookupReplyMessage() throws IOException {
        List nodes = new ArrayList(3);
        for (int i = 0; i < 3; i++) {
            nodes.add(new Node(InetAddress.getByName("127.0.0.1"), 1, Identifier.randomIdentifier()));
        }
        Node node = new Node(InetAddress.getByName("172.16.1.223"), 1, Identifier.randomIdentifier());
        Message mess = new NodeReplyMessage(node, nodes);
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        DataOutputStream dout = new DataOutputStream(bout);
        mess.toStream(dout);
        byte[] data = bout.toByteArray();

        DataInputStream din = new DataInputStream(new ByteArrayInputStream(data));
        NodeReplyMessage incm = new NodeReplyMessage(din);

        assertEquals(node.getInetAddress(), incm.getOrigin().getInetAddress());
        assertEquals(node.getPort(), incm.getOrigin().getPort());
        assertEquals(node.getId(), incm.getOrigin().getId());
        assertEquals(node, incm.getOrigin());
        assertEquals(nodes, incm.getNodes());
    }


}
